﻿package com.rbac.system.service.impl;

import com.rbac.system.entity.Menu;
import com.rbac.system.entity.Permission;
import com.rbac.system.mapper.MenuMapper;
import com.rbac.system.mapper.PermissionMapper;
import com.rbac.system.service.PermissionDependencyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 权限依赖服务实现
 */
@Service
public class PermissionDependencyServiceImpl implements PermissionDependencyService {
    
    @Autowired
    private PermissionMapper permissionMapper;
    
    @Autowired
    private MenuMapper menuMapper;
    
    @Override
    public Set<Long> resolvePermissionDependencies(List<Long> permissionIds) {
        if (permissionIds == null || permissionIds.isEmpty()) {
            return new HashSet<>();
        }
        
        Set<Long> allPermissions = new HashSet<>(permissionIds);
        
        // 为每个权限添加其父级权限
        for (Long permissionId : permissionIds) {
            allPermissions.addAll(getParentPermissions(permissionId));
        }
        
        return allPermissions;
    }
    
    @Override
    public Set<Long> resolveMenuDependencies(List<Long> menuIds) {
        if (menuIds == null || menuIds.isEmpty()) {
            return new HashSet<>();
        }
        
        Set<Long> allMenus = new HashSet<>(menuIds);
        
        // 为每个菜单添加其父级菜单
        for (Long menuId : menuIds) {
            allMenus.addAll(getParentMenus(menuId));
        }
        
        return allMenus;
    }
    
    @Override
    public Set<Long> getRelatedMenusByPermissions(List<String> permissionCodes) {
        if (permissionCodes == null || permissionCodes.isEmpty()) {
            return new HashSet<>();
        }
        
        Set<Long> relatedMenus = new HashSet<>();
        
        for (String permissionCode : permissionCodes) {
            // 根据权限编码规则推断相关菜单
            Set<Long> menuIds = inferMenusByPermissionCode(permissionCode);
            relatedMenus.addAll(menuIds);
        }
        
        return relatedMenus;
    }
    
    @Override
    public Set<Long> getParentPermissions(Long permissionId) {
        Set<Long> parentPermissions = new HashSet<>();
        
        Permission permission = permissionMapper.selectById(permissionId);
        if (permission == null || permission.getParentId() == null || permission.getParentId() == 0) {
            return parentPermissions;
        }
        
        // 递归获取所有父级权限
        Long parentId = permission.getParentId();
        parentPermissions.add(parentId);
        parentPermissions.addAll(getParentPermissions(parentId));
        
        return parentPermissions;
    }
    
    @Override
    public Set<Long> getParentMenus(Long menuId) {
        Set<Long> parentMenus = new HashSet<>();
        
        Menu menu = menuMapper.selectById(menuId);
        if (menu == null || menu.getParentId() == null || menu.getParentId() == 0) {
            return parentMenus;
        }
        
        // 递归获取所有父级菜单
        Long parentId = menu.getParentId();
        parentMenus.add(parentId);
        parentMenus.addAll(getParentMenus(parentId));
        
        return parentMenus;
    }
    
    /**
     * 根据权限编码推断相关菜单
     */
    private Set<Long> inferMenusByPermissionCode(String permissionCode) {
        Set<Long> menuIds = new HashSet<>();

        // 权限编码格式通常为：模块:功能:操作，如 user:profile:view
        // 需要确保用户有访问对应菜单的权限

        if (permissionCode.startsWith("user:")) {
            // 用户相关权限，需要个人中心菜单权限
            menuIds.addAll(findMenusByCode("profile"));
            // 确保有个人中心的访问权限
            menuIds.addAll(findMenusByPath("/profile"));
        } else if (permissionCode.startsWith("admin:")) {
            // 管理员权限，需要系统管理相关菜单权限
            if (permissionCode.contains("user")) {
                menuIds.addAll(findMenusByCode("user-management"));
                menuIds.addAll(findMenusByPath("/system/user"));
                menuIds.addAll(findMenusByCode("system")); // 系统管理目录
            } else if (permissionCode.contains("role")) {
                menuIds.addAll(findMenusByCode("role-management"));
                menuIds.addAll(findMenusByPath("/system/role"));
                menuIds.addAll(findMenusByCode("system"));
            } else if (permissionCode.contains("menu")) {
                menuIds.addAll(findMenusByCode("menu-management"));
                menuIds.addAll(findMenusByPath("/system/menu"));
                menuIds.addAll(findMenusByCode("system"));
            } else if (permissionCode.contains("permission")) {
                menuIds.addAll(findMenusByCode("permission-management"));
                menuIds.addAll(findMenusByPath("/system/permission"));
                menuIds.addAll(findMenusByCode("system"));
            }
        }

        return menuIds;
    }
    
    /**
     * 根据菜单编码查找菜单ID
     */
    private Set<Long> findMenusByCode(String menuCode) {
        Set<Long> menuIds = new HashSet<>();

        try {
            // 查找匹配的菜单
            List<Menu> menus = menuMapper.selectList(new Menu());
            for (Menu menu : menus) {
                if (menu.getMenuCode() != null && menu.getMenuCode().contains(menuCode)) {
                    menuIds.add(menu.getId());
                    // 同时添加父级菜单
                    menuIds.addAll(getParentMenus(menu.getId()));
                }
            }
        } catch (Exception e) {
            // 忽略查询错误，返回空集合
        }

        return menuIds;
    }

    /**
     * 根据菜单路径查找菜单ID
     */
    private Set<Long> findMenusByPath(String path) {
        Set<Long> menuIds = new HashSet<>();

        try {
            // 查找匹配的菜单
            List<Menu> menus = menuMapper.selectList(new Menu());
            for (Menu menu : menus) {
                if (menu.getPath() != null && menu.getPath().equals(path)) {
                    menuIds.add(menu.getId());
                    // 同时添加父级菜单
                    menuIds.addAll(getParentMenus(menu.getId()));
                }
            }
        } catch (Exception e) {
            // 忽略查询错误，返回空集合
        }

        return menuIds;
    }
}


